<?php

namespace App\Kits\Services;


use App\Kits\Errors\ExecuteException;
use Illuminate\Foundation\Auth\User;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
use Spatie\Permission\Models\Role;

/**
 * 该类需要
 * 1、安装 spatie/laravel-permission
 * 2、开启AuthServiceProvider中注释的配置
 * 3、User模型添加HasRole Trait
 * Class LibAuthService
 * @package App\Kits\Services
 */
class LibAuthService
{
    const USER_CAN_SCOPES_KEY = 'user.can.scopes_key';

    /**
     * 通过用户获取登录Token
     * @param User $user
     * @param string|null $ruleName
     * @return string
     * @throws ExecuteException
     */
    public static function getTokenByUser(User $user, string $ruleName = null)
    {
        if (is_null($ruleName)) {
            $ruleName = $user->roles()->pluck('desc')->join(',');
        }
        $nickname = $user['nickname'] ?? '';
        $mobile = $user['mobile'] ?? '';
        $tokenName = "【" . trans('auth' . $ruleName) . "】{$nickname} {$mobile}";
        if (!isset($user->scopes)) {
            $user['scopes'] = collect($user->roles)->pluck('name');
        }
        return self::generateTokenByUser($user, $tokenName, $user->getRoleNames()->toArray());
    }


    /**
     * 创建新token
     * @param User $user
     * @param string $tokenName
     * @param array $scopes
     * @return string
     * @throws ExecuteException
     */
    public static function generateTokenByUser(User $user, string $tokenName, array $scopes = []): string
    {
        $tokenResult = $user->createToken($tokenName, $scopes);
        $token = $tokenResult->token;
        // 设置token可刷新时间
        $token->refresh_at = Carbon::now()->addSeconds(config('auth.refresh_ttl'));
        $save = $token->save();
        if (!$save) {
            throw new ExecuteException('生成登录权限失败');
        }
        return $tokenResult->accessToken;
    }

    /**
     * 获取同用户所有的权限，用于初始化可选权限
     * @param bool $fore
     * @return array
     */
    public static function getTokensCan(bool $fore = false)
    {
        if ($fore) {
            Cache::forget(self::USER_CAN_SCOPES_KEY);
        }
        return Cache::remember(self::USER_CAN_SCOPES_KEY, null, function () {
            return Role::query()->select('name', 'desc')->get()->keyBy('name')->map(function ($item) {
                return $item->desc;
            })->toArray();
        });
    }
}
